#include "Book.h"
#include "TcpClient.h"

Book::Book(QWidget* parent)
	: QWidget(parent) {
	m_strEnterDir.clear();
	m_strUploadFilePath.clear();
	m_pTimer = new QTimer;
	m_strSaveFilePath.clear();
	m_iRecved = 0;
	m_iTotal = 0;

	m_pBookListWidget = new QListWidget;	//文件名列表
	m_pREturnPB = new QPushButton("返回");
	m_pCreatDirPB = new QPushButton("创建文件夹");
	m_pDeleteDirPB = new QPushButton("删除文件夹");
	m_pRenamePB = new QPushButton("重命名文件(夹)");
	m_pFlushFilePB = new QPushButton("刷新文件");
	m_pUpLoadPB = new QPushButton("上传文件");
	m_pDownLoadPB = new QPushButton("下载文件");
	m_pDeleteFilePB = new QPushButton("删除文件");
	m_pShareFilePB = new QPushButton("共享文件");

	QVBoxLayout* pDirVBL = new QVBoxLayout;
	pDirVBL->addWidget(m_pREturnPB);
	pDirVBL->addWidget(m_pCreatDirPB);
	pDirVBL->addWidget(m_pDeleteDirPB);
	pDirVBL->addWidget(m_pRenamePB);
	pDirVBL->addWidget(m_pFlushFilePB);

	QVBoxLayout* pFileVBL = new QVBoxLayout;
	pFileVBL->addWidget(m_pUpLoadPB);
	pFileVBL->addWidget(m_pDownLoadPB);
	pFileVBL->addWidget(m_pDeleteFilePB);
	pFileVBL->addWidget(m_pShareFilePB);

	QHBoxLayout* pMain = new QHBoxLayout;
	pMain->addWidget(m_pBookListWidget);
	pMain->addLayout(pDirVBL);
	pMain->addLayout(pFileVBL);

	setLayout(pMain);
	flushFile();

	connect(m_pCreatDirPB, SIGNAL(clicked()),
		this, SLOT(createDir()));
	connect(m_pFlushFilePB, SIGNAL(clicked()),
		this, SLOT(flushFile()));
	connect(m_pDeleteDirPB, SIGNAL(clicked()),
		this, SLOT(deleteDir()));
	connect(m_pRenamePB, SIGNAL(clicked()),
		this, SLOT(reName()));
	connect(m_pBookListWidget, SIGNAL(doubleClicked(QModelIndex)),
		this, SLOT(enterDir(QModelIndex)));
	connect(m_pREturnPB, SIGNAL(clicked()),
		this, SLOT(returnPre()));
	connect(m_pUpLoadPB, SIGNAL(clicked()),
		this, SLOT(uploadFile()));
	connect(m_pTimer, SIGNAL(timeout()),
		this, SLOT(uploadFileData()));
	connect(m_pDeleteFilePB, SIGNAL(clicked()),
		this, SLOT(deleteFile()));
	connect(m_pDownLoadPB, SIGNAL(clicked()),
		this, SLOT(downloadFile()));
}

void Book::updateFileList(const PDU* pdu) {
	if (pdu == NULL) return;	//先将现有项清空
	QListWidgetItem* pItemTmp = NULL;
	int row = m_pBookListWidget->count();
	while (m_pBookListWidget->count() > 0) {
		pItemTmp = m_pBookListWidget->item(row - 1);
		m_pBookListWidget->removeItemWidget(pItemTmp);
		delete pItemTmp;
		row -= 1;
	}
	FileInfo* pFileInfo = NULL;	//根据pdu创建新项
	int iFileInfoCount = pdu->uiMsgLen / sizeof(FileInfo);
	for (int i = 0; i < iFileInfoCount; i++) {
		pFileInfo = (FileInfo*)(pdu->caMsg) + i;
		qDebug() << pFileInfo->caFileName << pFileInfo->iFileType;
		QListWidgetItem* pItem = new QListWidgetItem;
		if (pFileInfo->iFileType == 0) {
			pItem->setIcon(QIcon(QPixmap(":/map/folder.jpg")));
		}
		else if (pFileInfo->iFileType == 1) {
			pItem->setIcon(QIcon(QPixmap(":/map/file.jpg")));
		}
		pItem->setText(pFileInfo->caFileName);
		m_pBookListWidget->addItem(pItem);
	}
}

void Book::clearEnterDir()
{
	m_strEnterDir.clear();
	return;
}

QString Book::getEnterDir()
{
	return m_strEnterDir;
}

QString Book::getSavePath()
{
	return m_strSaveFilePath;
}

QFile* Book::getFileInstance()
{
	return &m_file;
}

void Book::createDir()
{
	QString strNewDir = QInputDialog::getText(this, "新建文件夹", "新文件夹名字");
	if (!strNewDir.isEmpty()) {
		if (strNewDir.size() >= 32) {
			QMessageBox::warning(this, "新建文件夹", "文件夹名字不能超过(也不能等于)32字符");
		}
		else {
			QString strName = TcpClient::getInstance().getStrName();
			QString curPath = TcpClient::getInstance().getCurPath();
			PDU* pdu = mkPDU(curPath.toLocal8Bit().size() + 1);
			pdu->uiMsgType = ENUM_MESSAGE_TYPE_CREATE_DIR_REQUEST;
			strncpy(pdu->caData, strName.toStdString().c_str(), strName.size());
			QByteArray temp = strNewDir.toLocal8Bit();
			strncpy(pdu->caData + 32, temp.data(), temp.size());
			//caMsg是int类型，不能使用strcpy赋值
			//当前路径放在caMsg，新文件夹名字放在caDate
			temp = curPath.toLocal8Bit();
			memcpy(pdu->caMsg, temp.data(), temp.size());
			//发送给服务器
			TcpClient::getInstance().getTcpSocket().write((char*)pdu, pdu->uiPDULen);
			free(pdu);
			pdu = NULL;
		}
	}
	else {
		QMessageBox::warning(this, "新建文件夹", "新文件夹名字不能为空");
	}
	return;
}

void Book::deleteDir()
{
	QString strCurPath = TcpClient::getInstance().getCurPath();
	QListWidgetItem* pItem = m_pBookListWidget->currentItem();
	if (pItem == NULL) {
		QMessageBox::warning(this, "删除文件", "未指定文件");
	}
	else {
		QString strDelName = pItem->text();
		//将当前路径放在PDU的caMsg内，注意末尾的'\0'
		PDU* pdu = mkPDU(strCurPath.toLocal8Bit().size() + 1);
		pdu->uiMsgType = ENUM_MESSAGE_TYPE_DELETE_DIR_REQUEST;
		QByteArray temp = strDelName.toLocal8Bit();
		memcpy(pdu->caData, temp.data(), temp.size());
		temp = strCurPath.toLocal8Bit();
		memcpy(pdu->caMsg, temp.data(), temp.size());
		TcpClient::getInstance().getTcpSocket().write((char*)pdu, pdu->uiPDULen);
		free(pdu);
		pdu = NULL;
	}
	return;
}

void Book::flushFile() {
	QString strCurPath = TcpClient::getInstance().getCurPath();
	QByteArray temp = strCurPath.toLocal8Bit();
	PDU* pdu = mkPDU(temp.size() + 1);
	pdu->uiMsgType = ENUM_MESSAGE_TYPE_FLUSH_FILE_REQUEST;
	memcpy((char*)(pdu->caMsg),
		temp.data(), temp.size());
	TcpClient::getInstance().getTcpSocket().write((char*)pdu, pdu->uiPDULen);
	free(pdu);
	pdu = NULL;
}

void Book::reName()
{
	QString strCurPath = TcpClient::getInstance().getCurPath();
	QListWidgetItem* pItem = m_pBookListWidget->currentItem();
	QString strCurFileName = pItem->text();
	QString strNewFileName = QInputDialog::getText(this,
		"重命名文件(夹)", "请输入新文件名");
	QByteArray temp = strNewFileName.toLocal8Bit();
	if (temp.size() >= 32) {
		QMessageBox::warning(this, "重命名文件(夹)",
			"文件名大小超过(包含)32字节");
	}
	else {
		//将老名字+新名字 放在caData里
		temp = strCurPath.toLocal8Bit();
		PDU* pdu = mkPDU(temp.size() + 1);
		pdu->uiMsgType = ENUM_MESSAGE_TYPE_RENAME_FILE_REQUEST;
		memcpy(pdu->caMsg, temp.data(), temp.size());
		temp = strCurFileName.toLocal8Bit();
		memcpy(pdu->caData, temp.data(), temp.size());
		temp = strNewFileName.toLocal8Bit();
		memcpy(pdu->caData + 32, temp.data(), temp.size());

		TcpClient::getInstance().getTcpSocket().write((char*)pdu, pdu->uiPDULen);
		free(pdu);
		pdu = NULL;
	}
	qDebug() << "当前文件名：" << strCurFileName << " 替换为:" << strNewFileName;
	return;
}

void Book::enterDir(const QModelIndex& index)
{
	QString strDirName = index.data().toString();
	QString strCurPath = TcpClient::getInstance().getCurPath();
	m_strEnterDir = strDirName;
	QByteArray temp = strCurPath.toLocal8Bit();
	PDU* pdu = mkPDU(temp.size() + 1);
	pdu->uiMsgType = ENUM_MESSAGE_TYPE_ENTER_DIR_REQUEST;
	memcpy(pdu->caMsg, temp.data(), temp.size());
	temp = strDirName.toLocal8Bit();
	memcpy(pdu->caData, temp.data(), temp.size());
	TcpClient::getInstance().getTcpSocket().write((char*)pdu, pdu->uiPDULen);
	free(pdu);
	pdu = NULL;
	return;
}

void Book::returnPre()
{
	QString strCurPath = TcpClient::getInstance().getCurPath();
	QString strRootPath = "./" + TcpClient::getInstance().getStrName();
	if (strCurPath == strRootPath) {	//当前已是根目录
		QMessageBox::information(this, "返回上级", "返回失败，当前为根目录");
	}
	else {	//	"./aa/bb/cc" --> "./aa/bb"
		int index = strCurPath.lastIndexOf('/');
		strCurPath.remove(index, strCurPath.size() - index);
		TcpClient::getInstance().setCurPath(strCurPath);
		flushFile();
	}
	return;
}

void Book::uploadFile()
{
	//得到上传文件的绝对路径，不用写入PDU
	m_strUploadFilePath = QFileDialog::getOpenFileName();
	if (m_strUploadFilePath.isEmpty()) {
		QMessageBox::warning(this, "上传文件", "上传失败，上传文件不能为空！");
		return;
	}
	else {	//	"./aa/bb" --> "bb"
		int index = m_strUploadFilePath.lastIndexOf('/');
		QString strFileName = m_strUploadFilePath.right(
			m_strUploadFilePath.size() - index - 1);
		if (strFileName.toLocal8Bit().size() >= 32) {
			QMessageBox::warning(this, "上传文件", "警告：文件名大小不能超过32字节！");
			return;
		}
		QFile file(m_strUploadFilePath);
		qint64 fileSize = file.size();	//获得上传文件的大小
		QString strCurPath = TcpClient::getInstance().getCurPath();
		PDU* pdu = mkPDU(strCurPath.size() + 1);
		pdu->uiMsgType = ENUM_MESSAGE_TYPE_UPLOAD_FILE_REQUEST;
		QByteArray temp = strCurPath.toLocal8Bit();
		memcpy(pdu->caMsg, temp.data(), temp.size());
		sprintf(pdu->caData, "%s %lld",
			strFileName.toLocal8Bit().data(), fileSize);
		TcpClient::getInstance().getTcpSocket()
			.write((char*)pdu, pdu->uiPDULen);
		qDebug() << "写入数据为：" << pdu->caData;
		free(pdu);
		pdu = NULL;
		m_pTimer->start(1000);	//延迟1000ms后再开始发送文件数据，防止数据与请求粘连
	}
}

void Book::uploadFileData()
{
	m_pTimer->stop();
	QFile file(m_strUploadFilePath);
	if (!file.open(QIODevice::ReadOnly)) {	//文件打开失败
		QMessageBox::warning(this, "上传文件", "上传失败：当前上传文件路径不存在，请重试");
		return;
	}
	char* pBuffer = new char[4096];
	qint64 ret = 0;
	while (1) {
		ret = file.read(pBuffer, 4096);	//read()会返回实际读到的数据，用ret保存
		if (ret > 0 && ret <= 4096) {
			TcpClient::getInstance().getTcpSocket()
				.write(pBuffer, ret);
		}
		else if (ret == 0) {	//读到了文件末尾
			break;
		}
		else {	//数据出错
			QMessageBox::warning(this, "上传文件", "上传文件失败：读取文件失败");
			break;
		}
	}
	file.close();
	delete[]pBuffer;
	pBuffer = NULL;
}

void Book::deleteFile()
{
	QString strCurPath = TcpClient::getInstance().getCurPath();
	QString strFileName = m_pBookListWidget->currentItem()->text();
	QByteArray temp = strCurPath.toLocal8Bit();
	PDU* pdu = mkPDU(temp.size() + 1);
	pdu->uiMsgType = ENUM_MESSAGE_TYPE_DELETE_FILE_REQUEST;
	memcpy(pdu->caMsg, temp.data(), temp.size());
	temp = strFileName.toLocal8Bit();
	memcpy(pdu->caData, temp.data(), temp.size());
	TcpClient::getInstance().getTcpSocket().write((char*)pdu, pdu->uiPDULen);
	qDebug() << "当前删除路径为：" << strCurPath;
	qDebug() << "当前删除文件名为：" << strFileName;
	free(pdu);
	pdu = NULL;
	return;
}

void Book::downloadFile()
{
	QListWidgetItem* pItem = m_pBookListWidget->currentItem();
	if (pItem == NULL) {	//未选取有效项
		QMessageBox::information(this, "下载文件", "请选择要下载的文件");
		return;
	}
	QString strCurPath = TcpClient::getInstance().getCurPath();
	QString downloadFileName = pItem->text();
	QByteArray temp = strCurPath.toLocal8Bit();
	PDU* pdu = mkPDU(temp.size() + 1);
	pdu->uiMsgType = ENUM_MESSAGE_TYPE_DOWNLOAD_FILE_REQUEST;
	memcpy(pdu->caMsg, temp.data(), temp.size());
	temp = downloadFileName.toLocal8Bit();
	memcpy(pdu->caData, temp.data(), temp.size());
	QString strSaveFilePath = QFileDialog::getSaveFileName();
	if (strSaveFilePath.isEmpty()) {
		QMessageBox::warning(this, "下载文件", "保存路径不能为空");
		m_strSaveFilePath.clear();
	}
	else {
		m_strSaveFilePath = strSaveFilePath;
		TcpClient::getInstance().getTcpSocket().write((char*)pdu, pdu->uiPDULen);
	}
	free(pdu);
	pdu = NULL;

	return;
}

void Book::downloadFileData()
{
}
